package com.winit.distributed.lock;

import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.concurrent.TimeUnit;

/**
 * @author liuming.li
 */
public class RedisDistributedLock implements DistributedLock{

    private static final Logger logger = LoggerFactory.getLogger(RedisDistributedLock.class);

    private final RedissonClient redissonClient;

    private final String lockPrefix;

    public RedisDistributedLock(RedissonClient redissonClient, String lockPrefix) {
        this.redissonClient = redissonClient;
        this.lockPrefix = lockPrefix;
    }

    public void lock(String lockKey, long leaseTime, TimeUnit unit) {
        String actualLockKey = getLockKey(lockKey);
        logger.info("阻塞式获取分布式锁 Key={} LeaseTime={} TimeUnit={}", actualLockKey, leaseTime, unit);
        RLock lock = redissonClient.getLock(actualLockKey);
        lock.lock(leaseTime, unit);
    }

    public boolean tryLock(String lockKey, long waitTime, long leaseTime, TimeUnit unit) {
        String actualLockKey = getLockKey(lockKey);
        logger.info("尝试获取分布式锁 Key={} WaitTime={} LeaseTime={} TimeUnit={}", actualLockKey, waitTime, leaseTime, unit);
        RLock lock = redissonClient.getLock(actualLockKey);
        try {
            return lock.tryLock(waitTime, leaseTime, TimeUnit.MILLISECONDS);
        } catch (InterruptedException e) {
            logger.warn("获取分布式锁被中断: {}", e);
            return false;
        }
    }

    public void unlock(String lockKey) {
        String actualLockKey = getLockKey(lockKey);
        logger.info("释放分布式锁 Key={}", actualLockKey);
        RLock lock = redissonClient.getLock(actualLockKey);
        lock.unlock();
    }

    private String getLockKey(String lockKey) {
        return lockPrefix + lockKey;
    }
}
